


#include <iostream>
#include <cstdlib>
#include <string.h>

/*

https://blog.csdn.net/rankun1/article/details/78354153
https://blog.csdn.net/rankun1/article/details/78343678

*/



class TestA {

    public:
        TestA() { std::cout << "TestA constructor" << std::endl;}
        ~TestA() { std::cout << "TestA ~destructor" << std::endl;}
        TestA(int i) { std::cout <<"TestA contructor " << i << std::endl; }
        void print() {

            std::cout << "print" << std::endl;

        }
};



// void func(TestA& a) {
//     a.print();
// };

void func(TestA&& a) {
    a.print();
}

void test_case1() {
    TestA a(2);
    func(TestA(1));
    func(std::forward<TestA>(a));
}

using namespace std;

class CMyString
{
public:
	CMyString(char* pStr)
		: m_pStr(NULL)
		, m_nLen(0)
	{
		if (NULL != pStr)
		{
			m_nLen = static_cast<int>(strlen(pStr));
			m_pStr = new char[m_nLen + 1];
			memcpy(m_pStr, pStr, m_nLen);
			m_pStr[m_nLen] = 0;
			cout << "一般构造函数 str=" << m_pStr << endl;
		}		
	}
 
	CMyString(const CMyString& o)
		: m_pStr(NULL)
		, m_nLen(0)
	{
		if (NULL != o.m_pStr)
		{
			m_nLen = o.m_nLen;
			m_pStr = new char[m_nLen + 1];
			memcpy(m_pStr, o.m_pStr, m_nLen);
			m_pStr[m_nLen] = 0;
			cout << "拷贝构造函数 str=" << m_pStr << endl;
		}		
	}
	const CMyString& operator=(CMyString&& o)
	{
		char* pStrTmp = o.m_pStr;
		int nLen = o.m_nLen;
 
		o.m_pStr = m_pStr;
		o.m_nLen = m_nLen;
 
		m_pStr = pStrTmp;
		m_nLen = nLen;	
		cout << "右值引用类型 重载赋值运算符 str=" << m_pStr << endl;
		return *this;
	}
	const CMyString& operator=(const CMyString& o)
	{
		if (this != &o)
		{
			if (NULL != m_pStr)
			{
				delete[] m_pStr;
				m_pStr = NULL;
			}
			m_nLen = o.m_nLen;
			if (NULL != o.m_pStr)
			{
				m_pStr = new char[m_nLen + 1];
				memcpy(m_pStr, o.m_pStr, m_nLen);
				m_pStr[m_nLen] = 0;
			}			
			cout << "重载赋值运算符 str=" << m_pStr << endl;
		}
		return *this;
	}	
 
	~CMyString()
	{
		if (NULL != m_pStr)
		{
			//cout << "析构函数 str=" << m_pStr << endl;
			delete m_pStr;			
		}		
	}
 
	char* GetData()
	{
		return m_pStr;
	}	
	CMyString(CMyString&& o)
		: m_pStr(NULL)
		, m_nLen(0)
	{
		char* pStrTmp = o.m_pStr;
		int nLen = o.m_nLen;
 
		o.m_pStr = m_pStr;
		o.m_nLen = m_nLen;
 
		m_pStr = pStrTmp;
		m_nLen = nLen;	
		cout << "右值引用类型 拷贝构造函数 str=" << m_pStr << endl;		
	}
	void swap(CMyString& o)
	{
		char* pStrTmp = o.m_pStr;
		int nLen = o.m_nLen;
 
		o.m_pStr = m_pStr;
		o.m_nLen = m_nLen;
 
		m_pStr = pStrTmp;
		m_nLen = nLen;		
	}
private:
	char* m_pStr;
	int m_nLen;
};

void CoreFun(CMyString t) 
{
	cout << "CoreFun" << endl;
}
 
void ICoreFun(CMyString& t) 
{
	cout << "ICoreFun" << endl;
	CoreFun(t);
}

template <typename T>
void CoreFun(T t)
{
	cout << "CoreFun" << endl;
}
 
template <typename T>
void ICoreFun(T&& t)
{
	cout << "ICoreFun" << endl;
	//CoreFun(t);
	CoreFun(std::forward<T>(t));
}


void swap_v1(CMyString& str1, CMyString& str2)
{
	cout << "********************************************" << endl;
	CMyString tmp = str1;
	str1 = str2;
	str2 = tmp;
	cout << "********************************************" << endl;
}


void swap_v2(CMyString& str1, CMyString& str2)
{
	cout << "********************************************" << endl;	
	CMyString tmp = std::move(str1);
	str1 = std::move(str2);
	str2 = std::move(tmp);
	cout << "********************************************" << endl;
}
void test_case0() {

	const char* pstr1 = "hello this is str1";
	const char* pstr2 = "hello this is str2";

	CMyString str1(const_cast<char *>(pstr1));
	CMyString str2(const_cast<char *>(pstr2));
	//swap_v1(str1, str2);
	swap_v2(str1, str2);
	cout << "str1.GetData:" << str1.GetData() << endl;

}
void test_case2() {

    const char* str = "hello this is the lvalue";

    CMyString lvalue(const_cast<char *>(str));
	ICoreFun(lvalue);

    const char* str2 = "hello this is the rvalue";
    ICoreFun(CMyString(const_cast<char*>(str2)));

}

void test_case3() {

    const char* str1 = "hello this is the string 1";
    const char* str2 = "hello this is the string 2";

    CMyString myString1(const_cast<char*>(str1));
    CMyString myString2 = const_cast<char*>(str2);

    myString2 = myString1;
    CMyString myString3(myString2);
}

void test_case4() {

	CMyString str1(const_cast<char *>("hello this is str1"));
	CMyString str2(const_cast<char*>("hello this is str2"));
 
	swap(str1, str2);
 
	cout << "str1.GetData:" << str1.GetData() << endl;
    cout << "str2.GetData:" << str2.GetData() << endl;
}

void test_case5() {

    CMyString str1(const_cast<char *>("hello this is str1"));
	CMyString str2(const_cast<char*>("hello this is str2"));
 
	str1.swap(str2);
 
	cout << "str1.GetData:" << str1.GetData() << endl;
    cout << "str2.GetData:" << str2.GetData() << endl;

}

CMyString GetCMyString()
{
	return CMyString(const_cast<char*>("hello this is the other one"));
}


void test_case6() {

    CMyString str(const_cast<char*>("this is str"));
	str	= GetCMyString();
    cout << "str.GetData:" << str.GetData() << endl;

}

void test_case7() {

    CMyString str1(const_cast<char*>("hello this is str1"));
	CMyString str2(const_cast<char*>("hello this is str2"));
	swap(str1, str2);
	cout << "str1.GetData" << str1.GetData() << endl;
	cout << "str2.GetData" << str2.GetData() << endl;

}

// template <typename T>
// void wrapper(T u) {
//     fun(u);
// }

// class MyClass {};

// void fun(MyClass& a) { std::cout << "in fun(MyClass&)\n"; }
// void fun(const MyClass& a) { std::cout << "in fun(const MyClass&)\n"; }
// void fun(MyClass&& a) { std::cout << "in fun(MyClass &&)\n"; }

// void test_case8() {
// 	 MyClass a;
//     const MyClass b;

//     fun(a);
//     fun(b);
//     fun(MyClass());

//     std::cout << "----- Wrapper ------\n";
//     wrapper(a);
//     wrapper(b);
//     wrapper(MyClass());

// }

template <typename T>
void wrapper(T &&u) { // 万能引用
    func(std::forward<T>(u)); // 完美转发
}

class MyClass {};

void func(MyClass& a) { std::cout << "in func(MyClass&)\n"; }
void func(const MyClass& a) { std::cout << "in func(const MyClass&)\n"; }
void func(MyClass&& a) { std::cout << "in func(MyClass &&)\n"; }

void test_case9() {
	MyClass a;
    const MyClass b;

    func(a);
    func(b);
    func(MyClass());

    std::cout << "----- Wrapper ------\n";
    wrapper(a);
    wrapper(b);
    wrapper(MyClass());

}


int main() {

	test_case0();
    //test_case1();
    //test_case2();
    //test_case3();
    //test_case4();
    //test_case5();
    //test_case6();
    //test_case7();
	//test_case8();
    //test_case9();
	return 0;
}